/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "执行节点.h"
#include "节点/节点树.h"
#include "节点/插座/C_数值插座.h"
#include "节点/插座/C_物体插座.h"
#include "节点/插座/通用插座.h"
#include "节点/socket_utils.h"
#include "../../node后端.h"


#define DEF_执行状态_准备 0
#define DEF_执行状态_进行 1
#define DEF_执行状态_完成 2


static void f_Operator执行节点(S_结构对象指针 ops) {
	C_手动执行节点* node = (C_手动执行节点*)ops;
	node->f_set是否要更新(true);
	node->m_执行状态 = DEF_执行状态_准备;
}



C_手动执行节点::C_手动执行节点(S_设备环境& ctx) : C_节点基类("手动执行节点") {
	m_执行Ops = f_alloc_Ops(f_Operator执行节点, (S_结构对象指针)this);
	m_执行状态 = DEF_执行状态_完成;
}

C_手动执行节点::~C_手动执行节点() {
}

bool C_手动执行节点::f_update() {
	bool value = true;

	if (m_执行状态 == DEF_执行状态_完成) {
		value = false;
		f_get输出插座(0)->f_setData(&value);
	} else if (m_执行状态 == DEF_执行状态_准备) {
		f_get输出插座(0)->f_setData(&value);
		m_执行状态 = DEF_执行状态_进行;
		f_set是否要更新(true);
	}
	return false;
}

void C_手动执行节点::f_set是否要更新(bool update) {
	if (update == false && m_执行状态 == DEF_执行状态_进行) {
		C_节点基类::f_set是否要更新(true);
		m_执行状态 = DEF_执行状态_完成;
	} else {
		C_节点基类::f_set是否要更新(update);
	}
	
}

C_节点基类* f_node_加载手动执行节点(S_设备环境& ctx, FILE* f) {
	C_手动执行节点* node = new C_手动执行节点(ctx);

	return node;
}

void f_node_保存手动执行节点(C_节点基类* n, FILE* f) {
	C_手动执行节点* node = dynamic_cast<C_手动执行节点*>(n);

}









/*void f_添加预设插座(C_节点基类* node, E_插座方向 插座方向, int16 插座添加位置, C_插座基类* socket) {
	node->f_add插座(socket, 插座方向, 插座添加位置);

	for (auto& e : node->m_UI部件) {
		if (插座方向 == E_插座方向::e_插座Type_输入) {
			static_cast<C_节点面板*>(e)->f_addInSocket(socket, 插座添加位置);
		}
		else {
			static_cast<C_节点面板*>(e)->f_addOutSocket(socket, 插座添加位置);
		}
	}
	//子集输入输出节点插座同步
	std::vector<C_节点基类*> Nodes = f_get子集输入输出节点(node, 插座方向);

	if (插座方向 == E_插座方向::e_插座Type_输入) {
		for (auto& 输入组节点 : Nodes) {
			auto* outGroupSocket = f_创建节点插座(L"in", E_值类型::e_插座Type_引用数据);
			输入组节点->f_add插座(outGroupSocket, E_插座方向::e_插座Type_输出, 插座添加位置);
			for (auto& e : 输入组节点->m_UI部件) {
				static_cast<C_节点面板*>(e)->f_addOutSocket(outGroupSocket, 插座添加位置);
			}
		}
	}
	else {
		for (auto& 输出组节点 : Nodes) {
			auto* inGroupSocket = f_创建节点插座(L"out", E_值类型::e_插座Type_引用数据);
			输出组节点->f_add插座(inGroupSocket, E_插座方向::e_插座Type_输入, 插座添加位置);

			for (auto& e : 输出组节点->m_UI部件) {
				static_cast<C_节点面板*>(e)->f_addInSocket(inGroupSocket, 插座添加位置);
			}
		}
	}
}*/



C_循环迭代节点::C_循环迭代节点(S_设备环境& ctx) : C_节点基类(DEF_循环头节点, E_节点类型::e_节点Type_循环迭代) {
	m_Name = L"循环";
	m_Ctx = ctx;

	m_子集节点树 = f_node_Create循环节点树(false);
	f_绑定子集节点树(m_子集节点树);

	auto 输入组节点 = new C_输入组节点(ctx, 2);
	m_子集节点树->f_添加节点(输入组节点);
	m_子集节点树->f_添加节点(new C_输出组节点(ctx));

	m_更新方式 = E_节点更新方式::e_节点更新_逐帧;


	C_插座基类* socket;
	DEF_创建UI32插座_I(L"索引");
	DEF_创建UI32插座_I(L"次数");

	DEF_UI32插座数据(f_get输入插座(1)) = 0;
	DEF_UI32插座数据(f_get输入插座(2)) = 1;

	auto* 输入组节点_socket = f_su_创建节点后端插座(L"索引", E_值类型::e_Type_UI32);
	输入组节点->f_add插座(输入组节点_socket, E_插座方向::e_插座Type_输出);
	输入组节点_socket = f_su_创建节点后端插座(L"次数", E_值类型::e_Type_UI32);
	输入组节点->f_add插座(输入组节点_socket, E_插座方向::e_插座Type_输出);
}

C_循环迭代节点::~C_循环迭代节点() {
}

bool C_循环迭代节点::f_update() {
	if (m_子集节点树->m_节点结构改变) {
		m_InNodes.clear();
		m_OutNudes.clear();
		f_get子集输入节点(m_InNodes);
		f_get子集输出节点(m_OutNudes);
	}

	uint32 i = DEF_UI32插座数据(f_get输入插座(1));
	uint32 num = DEF_UI32插座数据(f_get输入插座(2));
	for (uint32 i = 0; i < num; ++i) {
		m_InNodes[0]->f_get输出插座(1)->f_setData(&i);

		f_NT_StepUpdate节点(m_子集节点树, true);
	}

	for (auto& e : m_OutNudes) {
		uint32 num = e->f_get输入插座Num();
		for (uint32 i = 0; i < num; ++i) {
			auto* socket = e->f_get输入插座(i);
			auto* outSocket = f_get输出插座(i);

			outSocket->f_setData(socket->f_getData(0));
		}
	}
	
	return false;
}

void C_循环迭代节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void C_循环迭代节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}
//static std::string g编码 = "GBK";

std::string C_循环迭代节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";

	uint32 num = f_get输入插座Num();
	for (uint32 i = 3; i < num; ++i) {
		C_插座基类* inSocket = f_get输入插座(i)->f_getLinkOutSocket();
		if (inSocket) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, i, inSocket->m_Type);

			f_get输入插座(i)->f_setCode(inSocket->f_getCode(0));
			//if (f_get输入插座(i)->m_Type == E_值类型::e_插座Type_引用数据) {
			//}
		}
	}

	std::string 参数[2];

	C_节点树* rt = f_getThis节点树();

	
	//参数[0] = f_代码构建_插座变量(*f_get输入插座(1), rt);
	//参数[1] = f_代码构建_插座变量(*f_get输入插座(2), rt);

	if (参数[0].size() && 参数[1].size()) {
		m_Code += f_get输入插座(1)->f_构建变量代码(0);
		m_Code += f_get输入插座(2)->f_构建变量代码(0);

		参数[0] = f_get输入插座(1)->f_getCode(0);
		参数[1] = f_get输入插座(2)->f_getCode(0);


		//std::string name = f_WStringToString(f_get输入插座(1)->m_identifier);
		std::string 索引 = f_getName() + "_i";
		std::string 循环次数 = 索引 + "循环次数";

		m_Code += f_代码构建_新建变量忽略负数(参数[1], 循环次数);
		
		f_get输入插座(1)->f_setCode(索引);
		f_get输入插座(2)->f_setCode(循环次数);

		
		m_Code += "for(";
		m_Code += "uint32 " + 索引 + " = " + 参数[0] + "; ";
		//code += f_node_getDataTypeName(f_get输入插座(1)->m_Type) + " " + 索引 + " = " + inSocket1->f_getCode() + "; ";
		m_Code += 索引 + " < " + 循环次数 + "; ";
		m_Code += "++" + 索引;
		m_Code += "){\n";



		f_get子集输入节点(m_InNodes);
		for (auto& e : m_InNodes) {
			for (uint16 i = 0; i < num; ++i) {
				e->f_get输出插座(i)->f_setCode(f_get输入插座(i)->f_getCode(0));
			}
		}

		m_Code += f_NT_编译节点树(m_子集节点树, 定义, 声明);
		
		num = f_get输出插座Num();
		f_get子集输出节点(m_OutNudes);
		for (auto& e : m_OutNudes) {
			for (uint16 i = 0; i < num; ++i) {
				e->f_get输入插座(i)->f_setCode(f_get输出插座(i)->f_getCode(0));
			}
		}

		m_Code += "}\n";
	}

	return m_Code;
}

void C_循环迭代节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	f_NT_Release(m_子集节点树);
	
	std::vector<C_节点树*> trees = f_node_加载节点树(m_Ctx, f);
	if (trees.size()) m_子集节点树 = trees[0];
	f_绑定子集节点树(m_子集节点树);
	//m_Tree->f_set父节点(this);
}
void C_循环迭代节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	std::vector<C_节点树*> trees = { m_子集节点树 };
	f_node_保存节点树(trees, f);
}

C_节点基类* f_node_创建循环迭代节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_循环迭代节点(ctx);
}

C_节点基类* f_node_加载循环迭代节点(S_设备环境& ctx, FILE* f) {
	C_循环迭代节点* node = new C_循环迭代节点(ctx);

	return node;
}

void f_node_保存循环迭代节点(C_节点基类* n, FILE* f) {
	C_循环迭代节点* node = dynamic_cast<C_循环迭代节点*>(n);

}





C_跳过节点::C_跳过节点(S_设备环境& ctx) : C_节点基类(DEF_跳过节点, E_节点类型::e_节点Type_自定义) {
	m_Name = L"跳过";
	m_Ctx = ctx;

	C_插座基类* socket;
	//DEF_创建I8插座_I(L"判断");
	//DEF_创建UI32插座_I(L"次数");
	m_跳过返回 = f_alloc_EnumProp(nullptr, { {L"continue", ""}, {L"return", ""}, {L"back", ""}, {L"空", ""} }, L"跳过", 1);
	m_跳过返回.m_私有 = true;
}

C_跳过节点::~C_跳过节点() {
	f_prop_Release(m_跳过返回);
}

bool C_跳过节点::f_update() {
	return false;
}

std::string C_跳过节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	//C_节点树* rt = f_getThis节点树();
	switch (f_prop_enum(m_跳过返回)) {
		case 0: m_Code += "	continue;\n"; break;
		case 1: m_Code += "	return true;\n"; break;
		case 2: m_Code += "	break;\n"; break;
		case 3: m_Code += ""; break;
		default:
			break;
	}
	//m_Code += f_get输入插座(0)->f_构建变量代码();
	//m_Code += "if(" + f_get输入插座(0)->f_getCode() + "){\n";
	//if (m_当前节点所在节点树) {
	//	if (m_当前节点所在节点树->m_树类型 == E_节点树类型::e_type_循环节点树) {
	//		m_Code += "	break;\n";
	//	}
	//	else {
	//		m_Code += "	return true;\n";
	//	}
	//}
	//m_Code += "}\n";
	
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_跳过节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_跳过返回, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_跳过节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_跳过返回, 块);
	
	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建跳过节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_跳过节点(ctx);
}

C_节点基类* f_node_加载跳过节点(S_设备环境& ctx, FILE* f) {
	C_跳过节点* node = new C_跳过节点(ctx);
	return node;
}

void f_node_保存跳过节点(C_节点基类* n, FILE* f) {
	C_跳过节点* node = dynamic_cast<C_跳过节点*>(n);
}




C_循环节点::C_循环节点(S_设备环境& ctx) : C_节点基类(DEF_循环节点, E_节点类型::e_节点Type_循环) {
	m_Name = L"loop";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建UI32插座_I(L"索引");
	DEF_创建UI32插座_I(L"次数");

	DEF_创建UI32插座_O(L"索引");
	DEF_创建UI32插座_O(L"次数");

	DEF_UI32插座数据(f_get输入插座(1)) = 0;
	DEF_UI32插座数据(f_get输入插座(2)) = 1;


	m_循环尾节点名称 = f_alloc_StrProp(nullptr, L"循环尾节点");
	m_循环尾节点 = nullptr;
}

C_循环节点::~C_循环节点() {
	f_prop_Release(m_循环尾节点名称);
}

/*void C_循环节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void C_循环节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}*/

bool C_循环节点::f_update() {
	return false;
}

std::string C_循环节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "{\n";
	m_ReleaseCode = "";

	auto* socket = f_get输入插座(1)->f_getLinkOutSocket(0);

	uint32 num = f_get输入插座Num();
	for (uint32 i = 1; i < num; ++i) {
		m_Code += f_get输入插座(i)->f_构建变量代码(0);
	}

	std::string 索引 = f_getName();
	std::string 次数 = 索引 + "次数";
	索引 += "_i";
	
	m_Code += f_代码构建_新建变量忽略负数(f_get输入插座(2)->f_getCode(0), 次数);

	f_get输出插座(1)->f_setCode(索引);
	f_get输出插座(2)->f_setCode(次数);

	m_Code += "for(";
	m_Code += "uint32 " + 索引 + " = " + f_get输入插座(1)->f_getCode(0) + "; ";
	//code += f_node_getDataTypeName(f_get输入插座(1)->m_Type) + " " + 索引 + " = " + inSocket1->f_getCode() + "; ";
	m_Code += 索引 + " < " + 次数 + "; ";
	m_Code += "++" + 索引;
	m_Code += "){\n";

	return "";
}

void C_循环节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_循环尾节点名称, f);
}

void C_循环节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_循环尾节点名称, f);
}

C_节点基类* f_node_创建循环节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_循环节点(ctx);
}

C_节点基类* f_node_加载循环节点(S_设备环境& ctx, FILE* f) {
	C_循环节点* node = new C_循环节点(ctx);
	return node;
}

void f_node_保存循环节点(C_节点基类* n, FILE* f) {
	C_循环节点* node = dynamic_cast<C_循环节点*>(n);
}





C_迭代节点::C_迭代节点(S_设备环境& ctx) : C_节点基类(DEF_迭代节点, E_节点类型::e_节点Type_迭代) {
	m_Name = L"迭代";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建引用插座_I(L"array");

	DEF_创建引用插座_O(L"元素");
	DEF_创建I32插座_O(L"索引");
	

	m_循环尾节点名称 = f_alloc_StrProp(nullptr, L"循环尾节点");
	m_循环尾节点 = nullptr;

	m_开启多线程 = f_alloc_BoolProp(nullptr, L"开启多线程");
	m_开启多线程.m_私有 = true;
	f_prop_Bool(m_开启多线程) = false;

}

C_迭代节点::~C_迭代节点() {
	f_prop_Release(m_循环尾节点名称);
	f_prop_Release(m_开启多线程);
}

bool C_迭代节点::f_update() {
	return false;
}

std::string C_迭代节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_ReleaseCode = "";
	m_Code = "{\n";
	std::string name = f_getName();


	uint32 num = f_get输入插座Num() - 1;
	for (uint32 i = 1; i < num; ++i) {
		switch (f_get输入插座(i)->f_get接入的数据类型()) {
		case E_值类型::e_Type_F32_1D:
		case E_值类型::e_Type_I8_1D:

		case E_值类型::e_Type_I32_1D:
		case E_值类型::e_Type_UI32_1D:

		case E_值类型::e_Type_Vec2_1D:

		case E_值类型::e_Type_Vec3_1D:
		case E_值类型::e_Type_Vec3_2D:

		case E_值类型::e_Type_Vec4_1D:
		case E_值类型::e_Type_iVec2_1D:

		case E_值类型::e_Type_iVec3_1D:
		case E_值类型::e_Type_iVec3_2D:

		case E_值类型::e_Type_uVec2_1D:
		case E_值类型::e_Type_uVec3_1D:
		case E_值类型::e_Type_Mat4X4_1D:
		case E_值类型::e_Type_UI32_2D:

		case E_值类型::e_Type_多边形边1D:
		case E_值类型::e_Type_多边形元素:
		case E_值类型::e_Type_多边形元素1D:
			f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, i);
			break;
		default:
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, i, E_值类型::e_插座Type_引用数据);
			break;
		}
		
	}
	
	
	
	std::string 索引 = name + "_i";
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, -1, E_值类型::e_Type_UI32);
	auto* socket = f_get输出插座(-1);
	socket->f_setCode(索引);

	
	socket = f_get输入插座(1);
	socket->f_构建变量代码(0);
	std::string 元素数量 = name + "_元素数量";
	m_Code += f_代码构建_插座变量数组数量(*f_get输入插座(1), 元素数量);


	for (uint32 i = 2; i < num; ++i) {
		socket = f_get输入插座(i);
		m_Code += socket->f_构建变量代码(0);

		m_Code += 元素数量 + " = " + DEF_S(DEF_Min)"(" + 元素数量 + ", " + socket->f_getCode(0) + "->count);\n";
	}


	if (f_prop_Bool(m_开启多线程)) {
		m_Code += "#pragma omp parallel for\n";
	}
	m_Code += "for(";
	m_Code += "int32 " + 索引 + " = 0; ";
	m_Code += 索引 + " < " + 元素数量 + "; ";
	m_Code += "++" + 索引;
	m_Code += "){\n";


	
	for (uint32 i = 1; i < num; ++i) {
		std::string 元素 = name + "_元素" + f_整数值转字符串(i);

		socket = f_get输入插座(i);
		//m_Code += socket->f_构建变量代码();

		switch (socket->m_Type) {
		case E_值类型::e_Type_Vec3_Array1D: {
			m_Code += "vec3* " + 元素 + " = f_JIT_Fun_vec3_data(" + socket->f_getCode(0) + ");\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_Vec3);
			break;
		}
		case E_值类型::e_Type_多边形边1D: {
			m_Code += "S_边** " + 元素 + " = (S_边**)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_多边形边);
			break;
		}
		case E_值类型::e_Type_多边形边: {
			m_Code += "uvec2* " + 元素 + " = f_多边形_边_data(" + socket->f_getCode(0) + ");\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_uVec2);
			break;
		}
		case E_值类型::e_Type_F32_1D: {
			m_Code += "float32* " + 元素 + " = (float32*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_F32);
			break;
		}
		case E_值类型::e_Type_I8_1D: {
			m_Code += "int8* " + 元素 + " = (int8*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_I8);
			break;
		}
		case E_值类型::e_Type_I32_1D: {
			m_Code += "int32* " + 元素 + " = (int32*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_I32);
			break;
		}
		case E_值类型::e_Type_UI32_1D: {
			m_Code += "uint32* " + 元素 + " = (uint32*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_UI32);
			break;
		}
		case E_值类型::e_Type_Vec3_1D: {
			m_Code += "vec3* " + 元素 + " = (vec3*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_Vec3);
			break;
		}
		case E_值类型::e_Type_Vec3_2D: {
			m_Code += "S_Vec3Array** " + 元素 + " = (S_Vec3Array**)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_Vec3_1D);
			break;
		}
		case E_值类型::e_Type_Vec4_1D: {
			m_Code += "vec4* " + 元素 + " = (vec4*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_Vec4);
			break;
		}
		case E_值类型::e_Type_iVec2_1D: {
			m_Code += "ivec2* " + 元素 + " = (ivec2*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_iVec2);
			break;
		}
		case E_值类型::e_Type_iVec3_1D: {
			m_Code += "ivec3* " + 元素 + " = (ivec3*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_iVec3);
			break;
		}
		case E_值类型::e_Type_iVec3_2D: {
			m_Code += "S_iVec3Array** " + 元素 + " = (S_iVec3Array**)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_iVec3_1D);
			break;
		}
		case E_值类型::e_Type_UI32_2D: {
			m_Code += DEF_S(S_UI32Array**)" " + 元素 + " = (" + DEF_S(S_UI32Array**)")(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_UI32_1D);
			break;
		}
		case E_值类型::e_Type_Mat4X4_1D: {
			m_Code += "Mat44f* " + 元素 + " = (Mat44f*)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_Mat4X4);
			break;
		}
		case E_值类型::e_Type_多边形元素: {
			m_Code += DEF_S(S_面**)" " + 元素 + " = (S_面**)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_多边形面);
			break;
		}
		case E_值类型::e_Type_多边形元素1D: {
			m_Code += "S_多边形元素** " + 元素 + " = (S_多边形元素**)(" + socket->f_getCode(0) + "->ptr_userData);\n";
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_Type_多边形元素);
			break;
		}
		}

		f_get输出插座(i)->f_setCode(元素 + "[" + 索引 + "]");
	}


	
	释放 += m_ReleaseCode;

	return "";
}

C_插座基类* C_迭代节点::f_动态添加插座(E_插座方向 方向, std::vector<S_添加的插座>& 添加的插座) {
	//int32 num = f_get输入插座Num();
	int32 loc = 1;
	loc = f_get输入插座Num();
	C_插座基类* socket = f_get输入插座(-1);
	if (socket->f_isLink()) {
		socket = new C_引用数据插座(L"array");
		f_add插座(socket, E_插座方向::e_插座Type_输入, loc);
		添加的插座.push_back({ socket, loc });

		auto* outSocket = f_get输出插座(loc);
		socket = new C_引用数据插座(L"元素");
		f_add插座(socket, E_插座方向::e_插座Type_输出, loc);
		添加的插座.push_back({ socket, loc });
		
		return socket;
	}
	return nullptr;
}

int32 C_迭代节点::f_动态删除插座(E_插座方向 方向, std::vector<S_删除的插座>& 删除的插座) {
	//int32 num = f_get输入插座Num() - 1;
	
	int32 i = f_get输入插座Num() - 2;
	while (i >= 1) {
		auto* socket = f_get输入插座(i);
		if (socket->f_isLink() == false) {
			f_del插座(i, 方向);
			删除的插座.push_back({ i, E_插座方向::e_插座Type_输入 });

			f_del插座(i, E_插座方向::e_插座Type_输出);
			删除的插座.push_back({ i, E_插座方向::e_插座Type_输出 });
		}
		--i;
	}
	
	return -1;
}

void C_迭代节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_循环尾节点名称, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_开启多线程, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_迭代节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_循环尾节点名称, 块);
	f_prop_Save(m_开启多线程, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建迭代节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_迭代节点(ctx);
}

C_节点基类* f_node_加载迭代节点(S_设备环境& ctx, FILE* f) {
	C_迭代节点* node = new C_迭代节点(ctx);
	return node;
}

void f_node_保存迭代节点(C_节点基类* n, FILE* f) {
	C_迭代节点* node = dynamic_cast<C_迭代节点*>(n);
}





C_循环尾节点::C_循环尾节点(S_设备环境& ctx) : C_节点基类(DEF_循环尾节点, E_节点类型::e_节点Type_循环尾) {
	m_Name = L"End";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建引用插座_I(L"元素");
	DEF_创建引用插座_O(L"元素");

	//f_get输入插座(1)->f_set多输入();
	m_循环节点 = nullptr;

}

C_循环尾节点::~C_循环尾节点() {

}

bool C_循环尾节点::f_update() {

	return false;
}

std::string C_循环尾节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();

	uint32 num = f_get输入插座Num() - 1;

	std::string 返回变量定义;
	std::string 返回变量拷贝;

	for (uint32 i = 1; i < num; ++i) {
		f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, i);

		auto* socket = f_get输入插座(i);
		socket->f_构建变量代码(0);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, socket->m_Type);

		
		
		
		f_get输出插座(i)->f_setCode(socket->f_getCode(0));
		continue;

		std::string 变量名称 = name + f_整数值转字符串(i);
		switch (socket->m_Type) {	
			case E_值类型::e_Type_F32: 
				返回变量定义 += DEF_S(float32)" " + 变量名称 + ";\n";
				break;
			case E_值类型::e_Type_I8: 
				返回变量定义 += DEF_S(int8)" " + 变量名称 + ";\n";
				break;
			case E_值类型::e_Type_I16: 返回变量定义 += DEF_S(int16)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_I32: 返回变量定义 += DEF_S(int32)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_I64: 返回变量定义 += DEF_S(int64)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_Vec2: 返回变量定义 += DEF_S(vec2)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_Vec3: 返回变量定义 += DEF_S(vec3)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_Vec4: 返回变量定义 += DEF_S(vec4)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_uVec2: 返回变量定义 += DEF_S(uvec2)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_uVec3: 返回变量定义 += DEF_S(uvec3)" " + 变量名称 + ";\n"; break;
			case E_值类型::e_Type_uVec4: 返回变量定义 += DEF_S(uvec4)" " + 变量名称 + ";\n"; break;
				//变量名称 = name;
				
			default:
				变量名称 = socket->f_getCode(0);
				f_get输出插座(i)->f_setCode(变量名称);
				continue;
		}

		返回变量拷贝 += 变量名称 + " = " + socket->f_getCode(0) + ";\n";
		f_get输出插座(i)->f_setCode(变量名称);
	}
	

	if (m_区域父节点) {
		if (m_区域父节点->m_区域父节点) {
			m_区域父节点->m_区域父节点->m_Code += 返回变量定义;

			m_区域父节点->m_区域父节点->m_Code += m_区域父节点->m_Code;
			m_区域父节点->m_区域父节点->m_Code += m_区域父节点->m_ReleaseCode;
			

			m_区域父节点->m_区域父节点->m_Code += m_ReleaseCode;

			m_区域父节点->m_区域父节点->m_Code += 返回变量拷贝;

			m_区域父节点->m_区域父节点->m_Code += "}\n";
			m_区域父节点->m_区域父节点->m_Code += "}\n";
			
		}
		else {
			m_Code += 返回变量定义;

			m_Code += m_区域父节点->m_Code;
			m_Code += m_区域父节点->m_ReleaseCode;
			m_Code += m_ReleaseCode;

			m_Code += 返回变量拷贝;

			m_Code += "}\n";
			m_Code += "}\n";
		}
	}
	释放 += m_ReleaseCode;
	return m_Code;
}

C_插座基类* C_循环尾节点::f_动态添加插座(E_插座方向 方向, std::vector<S_添加的插座>& 添加的插座) {
	int32 loc = f_get输入插座Num();

	C_插座基类* socket = f_get输入插座(-1);
	if (socket->f_isLink()) {
		//DEF_创建引用插座_I(L"array");
		socket = new C_引用数据插座(L"array");
		f_add插座(socket, E_插座方向::e_插座Type_输入, loc);
		添加的插座.push_back({ socket, loc });

		socket = new C_引用数据插座(L"元素");
		f_add插座(socket, E_插座方向::e_插座Type_输出, loc);
		添加的插座.push_back({ socket, loc });

		return socket;
	}
	return nullptr;
}

int32 C_循环尾节点::f_动态删除插座(E_插座方向 方向, std::vector<S_删除的插座>& 删除的插座) {
	int32 num = f_get输入插座Num() - 1;
	//bool 删除插座 = false;
	for (int32 i = 1; i < num; ++i) {
		auto* socket = f_get输入插座(i);
		if (socket->f_isLink() == false && i >= 2) {
			f_del插座(i, E_插座方向::e_插座Type_输入);
			f_del插座(i, E_插座方向::e_插座Type_输出);

			删除的插座.push_back({ i, E_插座方向::e_插座Type_输入 });
			删除的插座.push_back({ i, E_插座方向::e_插座Type_输出 });
			return i;
		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, i, E_值类型::e_插座Type_引用数据);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, i, E_值类型::e_插座Type_引用数据);
		}
	}
	return -1;
}

C_节点基类* f_node_创建循环尾节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_循环尾节点(ctx);
}

C_节点基类* f_node_加载循环尾节点(S_设备环境& ctx, FILE* f) {
	C_循环尾节点* node = new C_循环尾节点(ctx);
	return node;
}

void f_node_保存循环尾节点(C_节点基类* n, FILE* f) {
	C_循环尾节点* node = dynamic_cast<C_循环尾节点*>(n);
}

void f_配对循环节点头和尾(C_节点基类* node_b, C_循环尾节点* node_e) {

	switch (node_b->m_Type) {
	case E_节点类型::e_节点Type_迭代: {
		((C_迭代节点*)node_b)->m_循环尾节点 = node_e;
		node_e->m_循环节点 = node_b;

		f_prop_Str(((C_迭代节点*)node_b)->m_循环尾节点名称) = node_e->f_getWName();
		break;
	}

	case E_节点类型::e_节点Type_循环: {
		((C_循环节点*)node_b)->m_循环尾节点 = node_e;
		node_e->m_循环节点 = node_b;

		f_prop_Str(((C_循环节点*)node_b)->m_循环尾节点名称) = node_e->f_getWName();
		break;
	}
	default:
		break;
	}

	node_b->m_区域内节点.insert(node_e);
}

















C_分支判断节点::C_分支判断节点(S_设备环境& ctx) : C_节点基类(DEF_分支判断节点, E_节点类型::e_节点Type_判断) {
	m_Name = L"判断";
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建I32插座_I(L"条件");
	DEF_创建I32插座_O(L"开关");

	m_反向 = f_alloc_BoolProp(nullptr, L"反转");
	m_反向.m_私有 = true;
	f_prop_Bool(m_反向) = false;

	m_布尔 = f_alloc_BoolProp(nullptr, L"布尔");
	m_布尔.m_私有 = true;
	f_prop_Bool(m_布尔) = true;

	m_Case = f_alloc_I32Prop(nullptr, L"case");
	m_Case.m_私有 = true;
	f_prop_I32(m_Case) = 0;
}

C_分支判断节点::~C_分支判断节点() {
	f_prop_Release(m_反向);
	f_prop_Release(m_布尔);
	f_prop_Release(m_Case);
}

bool C_分支判断节点::f_update() {

	//f_NT_StepUpdate节点(m_子树, true);

	return false;
}

std::string C_分支判断节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	m_Code = "{\n";

	m_Code += socket1->f_构建变量代码(0);

	auto 条件 = socket1->f_getCode(0);
	
	//m_Code += "if(" + f_代码构建_属性变量(m_反向, f_getThis节点树()) + "){\n";
	//m_Code += 条件 + " = (!" + 条件 + ");\n";
	//m_Code += "}\n";


	//m_Code += "if(" + f_代码构建_属性变量(m_布尔, f_getThis节点树()) + " == false){\n";
	//m_Code += "}\n";
	if (f_prop_Bool(m_反向)) {
		if (f_prop_Bool(m_布尔)) {
			m_Code += "if(!" + 条件 + "){\n";
		}
		else {
			m_Code += "if(!" + 条件 + " == " + f_代码构建_属性变量(m_Case, f_getThis节点树()) + "){\n";
		}
	}
	else {
		if (f_prop_Bool(m_布尔)) {
			m_Code += "if(" + 条件 + "){\n";
		}
		else {
			m_Code += "if(" + 条件 + " == " + f_代码构建_属性变量(m_Case, f_getThis节点树()) + "){\n";
		}
	}

	
	m_Code += "const auto& " + name + " = " + 条件 + ";\n";

	f_get输出插座(1)->f_setCode(name);
	//if (m_区域父节点) {
	//	m_区域父节点->m_Code += m_Code;
	//	return "";
	//}
	//return m_Code;
	return "";
}

void C_分支判断节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);

	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		switch (文件块.m_版本号) {
			case 0 << 32 | 1: {
				const uint8* 下一次读取数据指针 = 文件块.m_data;

				下一次读取数据指针 = f_prop_Load(m_反向, 下一次读取数据指针);
				下一次读取数据指针 = f_prop_Load(m_布尔, 下一次读取数据指针);
				下一次读取数据指针 = f_prop_Load(m_Case, 下一次读取数据指针);
				break;
			}
		}
	}

	free(文件块.m_data);

}
void C_分支判断节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	S_文件块 文件块;
	文件块.m_块类型 = E_节点工程文件块类型::e_工程文件块_节点实例属性;
	文件块.m_版本号 = S_节点数据::g_文件版本号;

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_反向, 块);
	f_prop_Save(m_布尔, 块);
	f_prop_Save(m_Case, 块);
	switch (S_节点数据::g_文件版本号) {
		case 0 << 32 | 1: {
			
			break;
		}
		default:
			break;
	}
	
	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建分支判断节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_分支判断节点(ctx);
}

C_节点基类* f_node_加载分支判断节点(S_设备环境& ctx, FILE* f) {
	C_分支判断节点* node = new C_分支判断节点(ctx);
	return node;
}

void f_node_保存分支判断节点(C_节点基类* n, FILE* f) {
	C_分支判断节点* node = dynamic_cast<C_分支判断节点*>(n);

}




C_包节点::C_包节点(S_设备环境& ctx, C_节点树* link_tree) : C_节点基类(DEF_包节点, E_节点类型::e_节点Type_包) {
	m_Name = L"包";
	m_Ctx = ctx;
	m_更新方式 = E_节点更新方式::e_节点更新_逐帧;

	if (link_tree) {
		f_绑定子集节点树(link_tree);
	}
	else {
		auto* 子树 = f_node_Create包节点树(false, L"pack_");
		C_节点基类::f_绑定子集节点树(子树);

		auto 输入组节点 = new C_输入组节点(ctx);
		子树->f_添加节点(输入组节点);
		auto 输出组节点 = new C_输出组节点(ctx);
		子树->f_添加节点(输出组节点);

		输入组节点->m_插座可编辑 = true;
		输出组节点->m_插座可编辑 = true;
	}
	
	f_绑定this节点树(m_当前节点所在节点树);
	m_动画曲线列表 = f_an_创建曲线层();
}

C_包节点::~C_包节点() {
	
}

void C_包节点::f_get子集输入节点(std::vector<C_节点基类*>& inNodes) {
	inNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输入) {
			inNodes.emplace_back(e);
		}
	}
}

void C_包节点::f_get子集输出节点(std::vector<C_节点基类*>& outNodes) {
	outNodes.clear();
	for (auto& e : m_子集节点树->m_Nodes) {
		if (e->m_Type == E_节点类型::e_节点Type_组输出) {
			outNodes.emplace_back(e);
		}
	}
}

bool C_包节点::f_update() {
	if (m_子集节点树->m_节点结构改变) {
		m_InNodes.clear();
		m_OutNudes.clear();
		f_get子集输入节点(m_InNodes);
		f_get子集输出节点(m_OutNudes);
	}

	uint32 num = f_get输入插座Num();
	for (auto& e : m_InNodes) {
		for (uint32 i = 0; i < num; ++i) {
			e->f_get输出插座(i)->f_setData(f_get输入插座(i)->f_getData(0));
		}
	}
	
	f_NT_StepUpdate节点(m_子集节点树, true);

	num = f_get输出插座Num();
	for (auto& e : m_OutNudes) {
		for (uint32 i = 0; i < num; ++i) {
			f_get输出插座(i)->f_setData(e->f_get输入插座(i)->f_getData(0));
		}
	}
	
	return false;
}

S_动画曲线组* C_包节点::f_getAN曲线() {
	S_物体* m_Ob = f_get虚拟体();

	f_an_清除曲线通道(m_动画曲线列表);
	if (m_Ob) {
		if (m_Ob->m_位置) {
			f_an_添加曲线通道(m_动画曲线列表, m_Ob->m_位置);
		}
		if (m_Ob->m_旋转) {
			f_an_添加曲线通道(m_动画曲线列表, m_Ob->m_旋转);
		}
		if (m_Ob->m_缩放) {
			f_an_添加曲线通道(m_动画曲线列表, m_Ob->m_缩放);
		}
	}
	
	return m_动画曲线列表;
}

uint32 C_包节点::f_getAN曲线数量() {
	return m_动画曲线列表->通道num;
}

S_物体* C_包节点::f_get虚拟体() {
	for (auto& e : m_OutNudes) {
		uint32 num = e->f_get输入插座Num();
		for (uint32 i=0; i<num; ++i) {
			auto* socket = e->f_get输入插座(i);
			switch (socket->m_Type) {
				case E_值类型::e_Type_Object:
					return DEF_物体插座数据(e->f_get输入插座(i), 0);

			default:
				break;
			}
		}
	}
	return nullptr;
}

void C_包节点::f_入回收() {
	for (auto& e : m_OutNudes) {
		uint32 num = e->f_get输入插座Num();
		for (uint32 i = 0; i < num; ++i) {
			auto* socket = e->f_get输入插座(i);
			switch (socket->m_Type) {
			case E_值类型::e_Type_Object: {
				auto ob = DEF_物体插座数据(e->f_get输入插座(i), 0);
				if (ob) {
					f_NodeCtx_get默认场景()->f_remove物体(ob, E_场景物体容器类型::e_集合);
				}
				
				break;
			}
			default:
				break;
			}
		}
	}

	for (auto& n : m_子集节点树->m_Nodes) {
		n->f_入回收();
	}
}

void C_包节点::f_回收() {
	for (auto& e : m_OutNudes) {
		uint32 num = e->f_get输入插座Num();
		for (uint32 i = 0; i < num; ++i) {
			auto* socket = e->f_get输入插座(i);
			switch (socket->m_Type) {
			case E_值类型::e_Type_Object: {
				auto ob = DEF_物体插座数据(e->f_get输入插座(i), 0);
				if (ob) {
					f_NodeCtx_get默认场景()->f_add物体({ob}, E_场景物体容器类型::e_集合);
				}

				break;
			}
			default:
				break;
			}
		}
	}

	for (auto& n : m_子集节点树->m_Nodes) {
		n->f_回收();
	}
}

void C_包节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_NT_Release(m_子集节点树);

	std::vector<C_节点树*> trees = f_node_加载节点树(m_Ctx, f);
	if (trees.size()) m_子集节点树 = trees[0];
	f_绑定子集节点树(trees[0]);
}

void C_包节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	std::vector<C_节点树*> trees = { m_子集节点树 };
	f_node_保存节点树(trees, f);
}

C_节点基类* f_node_创建包节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_包节点(ctx, 子节点树);
}

C_节点基类* f_node_加载包节点(S_设备环境& ctx, FILE* f) {
	C_包节点* node = new C_包节点(ctx, nullptr);
	return node;
}

void f_node_保存包节点(C_节点基类* n, FILE* f) {
	C_包节点* node = dynamic_cast<C_包节点*>(n);

}




